﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FanaticDownBlock.Track
{
    ///<summary>轨道信息相关工具类。</summary>
    internal static class TrackInfoHelper
    {
        private record SimpleTrackInfo(double startTime, double duration);

        ///<summary>载入信息。</summary>
        public static TrackInfoList LoadInfo(string filePath)
        {
            var trackInfoList = new TrackInfoList();
            using var fileStream = File.Open(filePath, FileMode.Open);
            using var streamReader = new StreamReader(fileStream);
            while (streamReader.EndOfStream == false)
            {
                var line = streamReader.ReadLine();
                if (string.IsNullOrWhiteSpace(line)) continue;
                var parts = line.Split(' ', ',', '-', ':', ';');

                var trackIdStr = parts.ElementAtOrDefault(0);
                if (string.IsNullOrWhiteSpace(trackIdStr)) continue;
                if (int.TryParse(trackIdStr, out var trackId) == false) continue;

                var startTimeSecondStr = parts.ElementAtOrDefault(1);
                if (string.IsNullOrWhiteSpace(startTimeSecondStr)) continue;
                if (double.TryParse(startTimeSecondStr, out var startTimeSecond) == false) continue;

                var durationSecondStr = parts.ElementAtOrDefault(2);
                if (string.IsNullOrWhiteSpace(durationSecondStr)) continue;
                if (double.TryParse(durationSecondStr, out var durationSecond) == false) continue;

                var content = parts.ElementAtOrDefault(3);

                var trackInfo = new TrackInfo(trackId, startTimeSecond, durationSecond, content);
                trackInfoList.Add(trackInfo);
            }

            TrackInfoListSort(trackInfoList);

            return trackInfoList;
        }

        ///<summary>创建随机序列。</summary>
        public static TrackInfoList CreateRandom2()
        {
            var maxDuration = 4 * 60; // 4 分钟
            var trackInfoList = new TrackInfoList();

            var trackCount = 4;

            for (int i = 0; i < trackCount; i++)
            {
                var simpleTrackInfos = GenerateTrackList(maxDuration);
                foreach (var simpeTrackInfo in simpleTrackInfos)
                {
                    trackInfoList.Add(new TrackInfo()
                    {
                        TrackId = i,
                        StartTimeSecond = simpeTrackInfo.startTime,
                        DurationSecond = simpeTrackInfo.duration,
                    });
                }
            }

            TrackInfoListSort(trackInfoList);

            return trackInfoList;
        }

        public static TrackInfoList CreateRandom()
        {
            var maxDuration = 4 * 60; // 4 分钟
            var trackInfoList = new TrackInfoList();
            var count = 300;
            var trackCount = 4;

            for (int i = 0; i < trackCount; i++)
            {
                for (var j = 0; j < count; j++)
                {
                    var interval = 1d * maxDuration / count;

                    trackInfoList.Add(new TrackInfo()
                    {
                        TrackId = i,
                        StartTimeSecond = interval * j,
                        DurationSecond = interval * 0.7,
                    });
                }
            }

            TrackInfoListSort(trackInfoList);

            return trackInfoList;
        }

        private static IEnumerable<SimpleTrackInfo> GenerateTrackList(double maxDuration)
        {
            const double MIN_INTERVAL = 0.10;
            const double MAX_INTERVAL = 0.25;

            var lastEndTime = 0d;

            while (true)
            {
                var duration = Random.Shared.NextDouble() * (MAX_INTERVAL - MIN_INTERVAL) + MIN_INTERVAL;
                var startTime = Random.Shared.NextDouble() * (maxDuration - lastEndTime) + lastEndTime;

                lastEndTime = startTime + duration;

                if (lastEndTime >= maxDuration)
                {
                    //yield break;
                    break;
                }
                else
                {
                    yield return new SimpleTrackInfo(startTime, duration);
                }

            }

        }

        private static void TrackInfoListSort(TrackInfoList trackInfoList)
        {
            trackInfoList.Sort((a, b) =>
            {

                if (a.StartTimeSecond >= b.StartTimeSecond) return 1;
                return -1;
            });
        }

    }
}
